home *** CD-ROM | disk | FTP | other *** search
/ AMIGA-CD 2 / Amiga-CD - Volume 2.iso / gepackte_disketten / 1994 / 08_94_5.dms / 08_94_5.adf / term-4.0-Source.lha / termStatusDisplay.c < prev    next >
C/C++ Source or Header  |  1994-07-03  |  47KB  |  2,104 lines

  1. /*
  2. **    termStatusDisplay.c
  3. **
  4. **    Status information display routines
  5. **
  6. **    Copyright © 1990-1994 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* The information to be displayed. */
  13.  
  14. enum    {    INFO_STATUS,INFO_BUFFER,INFO_PROTOCOL,INFO_EMULATION,INFO_BAUDRATE,
  15.         INFO_PARAMETERS,INFO_CURRENTTIME,INFO_ONLINETIME,INFO_ONLINECOST };
  16.  
  17.     /* The current status line display mode. */
  18.  
  19. enum    {    MODE_SCREEN_NORMAL,MODE_SCREEN_COMPRESSED,MODE_WB_NORMAL,MODE_WB_COMPRESSED };
  20.  
  21.     /* Enumerated text boxes. */
  22.  
  23. enum    {    STATUSBOX_STATUS_FONT,STATUSBOX_PROTOCOL_TERMINAL,
  24.         STATUSBOX_RATE_PARAMETERS,STATUSBOX_TIME_ONLINE };
  25.  
  26.     /* The tags our private status gadget class responds to. */
  27.  
  28. #define SG_Status    (TAG_USER+1)
  29. #define SG_Font        (TAG_USER+2)
  30. #define SG_Protocol    (TAG_USER+3)
  31. #define SG_Emulation    (TAG_USER+4)
  32. #define SG_BaudRate    (TAG_USER+5)
  33. #define SG_Parameters    (TAG_USER+6)
  34. #define SG_CurrentTime    (TAG_USER+7)
  35. #define SG_OnlineTime    (TAG_USER+8)
  36. #define SG_OnlineCost    (TAG_USER+9)
  37.  
  38.     /* Special private information maintained and required
  39.      * by the status gadget class.
  40.      */
  41.  
  42. struct StatusInfo
  43. {
  44.     struct TextBox        *BoxArray[4],
  45.                 *BoxList;
  46.  
  47.     LONG             FullWidth;
  48.     LONG             FirstColumn;
  49.  
  50.     UWORD             Mask;
  51.     UWORD             Mode;
  52.  
  53.     LONG             LastWidth;
  54.  
  55.     UBYTE             Strings[8][20];
  56.  
  57.     struct SignalSemaphore     Semaphore;
  58.  
  59.     LONG             WindowWidth,
  60.                  WindowHeight,
  61.                  WindowFlags;
  62. };
  63.  
  64.     /* The status server passes this structure to the
  65.      * rendering routine if the status information
  66.      * is to be updated.
  67.      */
  68.  
  69. struct ObjectCarrier
  70. {
  71.     struct RastPort     *RPort;
  72.     struct TextBox    **BoxArray;
  73. };
  74.  
  75.     /* A custom message type for the display update server. */
  76.  
  77. struct UpdateMessage
  78. {
  79.     struct Message    VanillaMessage;
  80.  
  81.     APTR        Object;
  82.     UBYTE        Mode,
  83.             Type;
  84. };
  85.  
  86.     /* The following static strings are displayed in the status
  87.      * window.
  88.      */
  89.  
  90. STATIC STRPTR    ConfigBufferState[3],
  91.         ConfigEmulation[6],
  92.         ConfigParity[6],
  93.         ConfigStatus[8];
  94.  
  95.     /* Width of the status line text, required in case the user interface
  96.      * font happens to be proportional-spaced.
  97.      */
  98.  
  99. STATIC LONG             StatusLineWidth;
  100.  
  101.     /* Our local private status gadget class. */
  102.  
  103. STATIC struct IClass        *StatusGadgetClass;
  104.  
  105.     /* The status display update task. */
  106.  
  107. STATIC struct Task        *StatusDisplayTask;
  108. STATIC struct MsgPort        *StatusDisplayPort;
  109.  
  110.     /* Prototypes for this module. */
  111.  
  112. STATIC ULONG __regargs        SetStatusGadget(struct IClass *class,Object *object,struct opSet *SetInfo);
  113. STATIC ULONG __regargs        GetStatusGadget(struct IClass *class,Object *object,struct opGet *GetInfo);
  114. STATIC ULONG __regargs        RenderStatusGadget(struct IClass *class,Object *object,struct gpRender *RenderInfo);
  115. STATIC ULONG __regargs        DelStatusGadget(struct IClass *class,Object *object,Msg msg);
  116. STATIC ULONG __regargs        NewStatusGadget(struct IClass *class,Object *object,struct opSet *SetMethod);
  117. STATIC ULONG __saveds __asm    StatusGadgetDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg);
  118. STATIC VOID            FreeStatusGadgetClass(VOID);
  119. STATIC BYTE            NewStatusGadgetClass(VOID);
  120.  
  121.     /* GetStatusGadget():
  122.      *
  123.      *    Query information on the status gadget.
  124.      */
  125.  
  126. STATIC ULONG __regargs
  127. GetStatusGadget(struct IClass *class,Object *object,struct opGet *GetInfo)
  128. {
  129.     struct StatusInfo *StatusInfo = INST_DATA(class,object);
  130.  
  131.     switch(GetInfo -> opg_AttrID)
  132.     {
  133.         case SGA_FullWidth:
  134.  
  135.             *GetInfo -> opg_Storage = (ULONG)StatusInfo -> FullWidth;
  136.             return(1);
  137.  
  138.         default:
  139.  
  140.             return(DoSuperMethodA(class,object,(Msg)GetInfo));
  141.     }
  142. }
  143.  
  144.     /* SetStatusGadget():
  145.      *
  146.      *    Set certain attributes of the status gadget.
  147.      */
  148.  
  149. STATIC ULONG __regargs
  150. SetStatusGadget(struct IClass *class,Object *object,struct opSet *SetInfo)
  151. {
  152.     struct StatusInfo    *StatusInfo = INST_DATA(class,object);
  153.     LONG             i,j;
  154.     struct RastPort        *RPort;
  155.     struct TagItem        *Tag;
  156.  
  157.     DoSuperMethodA(class,object,(Msg)SetInfo);
  158.  
  159.         /* Make sure that the information is available and
  160.          * nobody else tries to modify it.
  161.          */
  162.  
  163.     ObtainSemaphore(&StatusInfo -> Semaphore);
  164.  
  165.         /* Obtain the new text to be displayed in the gadget. */
  166.  
  167.     for(i = SG_Status, j = 0 ; i <= SG_OnlineCost ; i++, j++)
  168.     {
  169.         if(Tag = FindTagItem(i,SetInfo -> ops_AttrList))
  170.         {
  171.             strcpy(StatusInfo -> Strings[j],(STRPTR)Tag -> ti_Data);
  172.  
  173.             StatusInfo -> Mask |= (1L << j);
  174.         }
  175.     }
  176.  
  177.         /* Release the lock. */
  178.  
  179.     ReleaseSemaphore(&StatusInfo -> Semaphore);
  180.  
  181.     if(AttemptLockLayerRom(Window -> RPort -> Layer))
  182.     {
  183.             /* Obtain the drawing area lock. */
  184.  
  185.         RPort = ObtainGIRPort(SetInfo -> ops_GInfo);
  186.  
  187.         UnlockLayerRom(Window -> RPort -> Layer);
  188.  
  189.         if(RPort)
  190.         {
  191.                 /* Normal, uncompressed status line? */
  192.  
  193.             if(StatusInfo -> Mode == MODE_WB_NORMAL)
  194.             {
  195.                     /* Take a look at the strings which have
  196.                      * changed and render the corresponding
  197.                      * text.
  198.                      */
  199.  
  200.                 for(i = 0 ; i < 8 ; i++)
  201.                 {
  202.                     if(StatusInfo -> Mask & (1L << i))
  203.                     {
  204.                         SZ_SetLine(RPort,StatusInfo -> BoxArray[i / 2],i % 2,StatusInfo -> Strings[i]);
  205.  
  206.                         StatusInfo -> Mask &= ~(1L << i);
  207.                     }
  208.                 }
  209.             }
  210.             else
  211.             {
  212.                 STATIC BYTE Offsets[8] =
  213.                 {
  214.                      0,
  215.                     -1,
  216.                     26,
  217.                     11,
  218.                     40,
  219.                     53,
  220.                     61,
  221.                     72
  222.                 };
  223.  
  224.                 struct Gadget    *Gadget;
  225.                 UBYTE         LineBuffer[90];
  226.                 WORD         i,j,k;
  227.                 LONG         Width,
  228.                          Left,
  229.                          Top;
  230.  
  231.                     /* Get the real gadget. */
  232.  
  233.                 Gadget = (struct Gadget *)object;
  234.  
  235.                     /* Fill the line with defaults. */
  236.  
  237.                 strcpy(LineBuffer,"         ·              ·             ·            ·       ·          ·         ");
  238.  
  239.                     /* Add the information strings. */
  240.  
  241.                 for(i = 0 ; i < 8 ; i++)
  242.                 {
  243.                     if(Offsets[i] >= 0)
  244.                     {
  245.                         j = strlen(StatusInfo -> Strings[i]);
  246.  
  247.                         for(k = 0 ; k < j ; k++)
  248.                             LineBuffer[Offsets[i] + k] = StatusInfo -> Strings[i][k];
  249.                     }
  250.                 }
  251.  
  252.                     /* Determine the pixel width of the string. */
  253.  
  254.                 Width = TextLength(RPort,LineBuffer,80);
  255.  
  256.                     /* Get the rendering top offset. */
  257.  
  258.                 Top = SetInfo -> ops_GInfo -> gi_Window -> Height + Gadget -> TopEdge;
  259.  
  260.                 SetDrMd(RPort,JAM2);
  261.  
  262.                     /* Are we to clear the area the last rendering
  263.                      * operation obscured?
  264.                      */
  265.  
  266.                 if(StatusInfo -> LastWidth && StatusInfo -> LastWidth != Width)
  267.                 {
  268.                     Left = (SetInfo -> ops_GInfo -> gi_Window -> Width - StatusInfo -> LastWidth) / 2;
  269.  
  270.                         /* Set the approriate rendering pen. */
  271.  
  272.                     if(SetInfo -> ops_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  273.                         SetAPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  274.                     else
  275.                         SetAPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  276.  
  277.                         /* Clear the area. */
  278.  
  279.                     RectFill(RPort,Left,Top,Left + StatusInfo -> LastWidth - 1,Top + Gadget -> Height - 3);
  280.                 }
  281.  
  282.                     /* Set the approriate rendering pens. */
  283.  
  284.                 if(SetInfo -> ops_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  285.                 {
  286.                     SetAPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN]);
  287.                     SetBPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  288.                 }
  289.                 else
  290.                 {
  291.                     SetAPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[TEXTPEN]);
  292.                     SetBPen(RPort,SetInfo -> ops_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  293.                 }
  294.  
  295.                     /* Remember the text pixel width. */
  296.  
  297.                 StatusInfo -> LastWidth = Width;
  298.  
  299.                     /* Display the status line. */
  300.  
  301.                 Move(RPort,(SetInfo -> ops_GInfo -> gi_Window -> Width - StatusInfo -> LastWidth) / 2,Top + RPort -> Font -> tf_Baseline);
  302.                 Text(RPort,LineBuffer,80);
  303.             }
  304.  
  305.                 /* Release the rendering area. */
  306.  
  307.             ReleaseGIRPort(RPort);
  308.         }
  309.     }
  310.  
  311.     return(1);
  312. }
  313.  
  314.     /* RenderStatusGadget():
  315.      *
  316.      *    Redraw the entire status gadget.
  317.      */
  318.  
  319. STATIC ULONG __regargs
  320. RenderStatusGadget(struct IClass *class,Object *object,struct gpRender *RenderInfo)
  321. {
  322.     struct StatusInfo    *StatusInfo    = INST_DATA(class,object);
  323.     struct RastPort        *RPort        = RenderInfo -> gpr_RPort;
  324.     BYTE             MustRender,
  325.                  UpdateOnly;
  326.     LONG             i;
  327.  
  328.     MustRender = TRUE;
  329.     UpdateOnly = FALSE;
  330.  
  331.     StatusInfo -> Mask |= 0xFF;
  332.  
  333.     if(MustRender)
  334.     {
  335.             /* Normal, uncompressed display? */
  336.  
  337.         if(StatusInfo -> Mode == MODE_WB_NORMAL)
  338.         {
  339.                 /* Refresh the entire imagery (the default)? */
  340.  
  341.             if(RenderInfo -> gpr_Redraw == GREDRAW_REDRAW && !UpdateOnly)
  342.             {
  343.                 struct Gadget    *Gadget = (struct Gadget *)object;
  344.                 LONG         X;
  345.  
  346.                     /* Don't let anyone modify the text. */
  347.  
  348.                 ObtainSemaphore(&StatusInfo -> Semaphore);
  349.  
  350.                     /* Get the new gadget left offset. */
  351.  
  352.                 if((X = (RenderInfo -> gpr_GInfo -> gi_Window -> Width - StatusInfo -> FullWidth) / 2) < 0)
  353.                     X = 0;
  354.  
  355.                 X += StatusInfo -> FirstColumn - SZ_GetBoxInfo(StatusInfo -> BoxList,BOX_LEFT);
  356.  
  357.                     /* Move the status line to the new location. */
  358.  
  359.                 SZ_SetBoxes(StatusInfo -> BoxList,-1,RenderInfo -> gpr_GInfo -> gi_Window -> Height + Gadget -> TopEdge);
  360.  
  361.                 if(X)
  362.                     SZ_MoveBoxes(StatusInfo -> BoxList,X,0);
  363.  
  364.                     /* Set the box title rendering pen. */
  365.  
  366.                 if(RenderInfo -> gpr_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  367.                     SZ_SetTitlePen(StatusInfo -> BoxList,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN],RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  368.                 else
  369.                     SZ_SetTitlePen(StatusInfo -> BoxList,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[TEXTPEN],RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  370.  
  371.                     /* Redraw the boxes. */
  372.  
  373.                 SZ_DrawBoxes(RPort,StatusInfo -> BoxList);
  374.  
  375.                     /* Redraw all the strings. */
  376.  
  377.                 ReleaseSemaphore(&StatusInfo -> Semaphore);
  378.             }
  379.  
  380.                 /* Update the information which has changed. */
  381.  
  382.             for(i = 0 ; i < 8 ; i++)
  383.             {
  384.                 if(StatusInfo -> Mask & (1L << i))
  385.                 {
  386.                     SZ_SetLine(RPort,StatusInfo -> BoxArray[i / 2],i % 2,StatusInfo -> Strings[i]);
  387.  
  388.                     StatusInfo -> Mask &= ~(1L << i);
  389.                 }
  390.             }
  391.         }
  392.         else
  393.         {
  394.             STATIC BYTE Offsets[8] =
  395.             {
  396.                  0,
  397.                 -1,
  398.                 26,
  399.                 11,
  400.                 40,
  401.                 53,
  402.                 61,
  403.                 72
  404.             };
  405.  
  406.             struct Gadget    *Gadget;
  407.             UBYTE         LineBuffer[90];
  408.             WORD         i,j,k;
  409.             LONG         Width,
  410.                      Left,
  411.                      Top;
  412.  
  413.                 /* Grab the access semaphore. */
  414.  
  415.             ObtainSemaphore(&StatusInfo -> Semaphore);
  416.  
  417.                 /* Get the real gadget info. */
  418.  
  419.             Gadget = (struct Gadget *)object;
  420.  
  421.                 /* Fill the line buffer with defaults. */
  422.  
  423.             strcpy(LineBuffer,"         ·              ·             ·            ·       ·          ·         ");
  424.  
  425.                 /* Fill in the information strings. */
  426.  
  427.             for(i = 0 ; i < 8 ; i++)
  428.             {
  429.                 if(Offsets[i] >= 0)
  430.                 {
  431.                     j = strlen(StatusInfo -> Strings[i]);
  432.  
  433.                     for(k = 0 ; k < j ; k++)
  434.                         LineBuffer[Offsets[i] + k] = StatusInfo -> Strings[i][k];
  435.                 }
  436.             }
  437.  
  438.                 /* Determine the pixel width of the line. */
  439.  
  440.             Width = TextLength(RPort,LineBuffer,80);
  441.  
  442.                 /* Get the line top offset. */
  443.  
  444.             Top = RenderInfo -> gpr_GInfo -> gi_Window -> Height + Gadget -> TopEdge;
  445.  
  446.             SetDrMd(RPort,JAM2);
  447.  
  448.                 /* Clear the previously written text if necessary. */
  449.  
  450.             if(StatusInfo -> LastWidth && RenderInfo -> gpr_Redraw != GREDRAW_REDRAW)
  451.             {
  452.                 Left = (RenderInfo -> gpr_GInfo -> gi_Window -> Width - StatusInfo -> LastWidth) / 2;
  453.  
  454.                 if(RenderInfo -> gpr_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  455.                     SetAPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  456.                 else
  457.                     SetAPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  458.  
  459.                 RectFill(RPort,Left,Top,Left + StatusInfo -> LastWidth - 1,Top + Gadget -> Height - 3);
  460.             }
  461.  
  462.                 /* Set the approriate rendering colours. */
  463.  
  464.             if(RenderInfo -> gpr_GInfo -> gi_Window -> Flags & WFLG_WINDOWACTIVE)
  465.             {
  466.                 SetAPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLTEXTPEN]);
  467.                 SetBPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[FILLPEN]);
  468.             }
  469.             else
  470.             {
  471.                 SetAPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[TEXTPEN]);
  472.                 SetBPen(RPort,RenderInfo -> gpr_GInfo -> gi_DrInfo -> dri_Pens[BACKGROUNDPEN]);
  473.             }
  474.  
  475.                 /* Remember last pixel width. */
  476.  
  477.             StatusInfo -> LastWidth = Width;
  478.  
  479.                 /* Render the status line. */
  480.  
  481.             Move(RPort,(RenderInfo -> gpr_GInfo -> gi_Window -> Width - StatusInfo -> LastWidth) / 2,Top + RPort -> Font -> tf_Baseline);
  482.             Text(RPort,LineBuffer,80);
  483.  
  484.                 /* Release the lock. */
  485.  
  486.             ReleaseSemaphore(&StatusInfo -> Semaphore);
  487.         }
  488.     }
  489.  
  490.     return(0);
  491. }
  492.  
  493.     /* DelStatusGadget():
  494.      *
  495.      *    Deallocate the status gadget.
  496.      */
  497.  
  498. STATIC ULONG __regargs
  499. DelStatusGadget(struct IClass *class,Object *object,Msg msg)
  500. {
  501.     struct StatusInfo *StatusInfo = INST_DATA(class,object);
  502.  
  503.     if(StatusInfo -> BoxList)
  504.         SZ_FreeBoxes(StatusInfo -> BoxList);
  505.  
  506.     return(DoSuperMethodA(class,object,msg));
  507. }
  508.  
  509.     /* NewStatusGadget():
  510.      *
  511.      *    Create a new status gadget.
  512.      */
  513.  
  514. STATIC ULONG __regargs
  515. NewStatusGadget(struct IClass *class,Object *object,struct opSet *SetMethod)
  516. {
  517.     struct Gadget    *NewGadget;
  518.     struct TagItem    *Item;
  519.     LONG         Mode;
  520.     struct Screen    *LocalScreen;
  521.  
  522.         /* Determine the status line mode (compressed or normal). */
  523.  
  524.     if(Item = FindTagItem(SGA_Mode,SetMethod -> ops_AttrList))
  525.     {
  526.         switch(Item -> ti_Data)
  527.         {
  528.             case MODE_WB_NORMAL:
  529.             case MODE_WB_COMPRESSED:
  530.  
  531.                 Mode = Item -> ti_Data;
  532.                 break;
  533.  
  534.             default:
  535.  
  536.                 return(NULL);
  537.         }
  538.     }
  539.     else
  540.         return(NULL);
  541.  
  542.         /* Set up the defaults, note that this class
  543.          * implementation can, strictly speaking, not
  544.          * be considered reentrant.
  545.          */
  546.  
  547.     if(SharedScreen)
  548.         LocalScreen = SharedScreen;
  549.     else
  550.         LocalScreen = DefaultPubScreen;
  551.  
  552.     SZ_SizeSetup(LocalScreen,&UserFont);
  553.  
  554.         /* Create the new object. */
  555.  
  556.     if(NewGadget = (struct Gadget *)DoSuperMethodA(class,object,(Msg)SetMethod))
  557.     {
  558.         struct StatusInfo    *StatusInfo = INST_DATA(class,NewGadget);
  559.         LONG             SizeGadgetWidth;
  560.  
  561.         StatusInfo -> WindowWidth = StatusInfo -> WindowHeight = 0;
  562.  
  563.             /* Determine the width of the window sizing gadget,
  564.              * hopefully these values are never going to be
  565.              * changed.
  566.              */
  567.  
  568.         if(LocalScreen -> Flags & SCREENHIRES)
  569.             SizeGadgetWidth = SIZE_GADGET_WIDTH_HIGH;
  570.         else
  571.             SizeGadgetWidth = SIZE_GADGET_WIDTH_LOW;
  572.  
  573.             /* Clear the extra information area. */
  574.  
  575.         memset(StatusInfo,0,sizeof(struct StatusInfo));
  576.  
  577.             /* Initialize the signal semaphore. */
  578.  
  579.         InitSemaphore(&StatusInfo -> Semaphore);
  580.  
  581.             /* Is it the `big one'? */
  582.  
  583.         if((StatusInfo -> Mode = Mode) == MODE_WB_NORMAL)
  584.         {
  585.             WORD         ColumnLeft[4],
  586.                      ColumnWidth[4];
  587.             struct TextBox    *Box;
  588.             LONG         i,Max = 0,Len,FullWidth,BoxCounter = 0;
  589.  
  590.             ColumnLeft[0] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_STATUS_TXT,MSG_TERMSTATUSDISPLAY_FONT_TXT,-1);
  591.             ColumnLeft[1] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT,MSG_TERMSTATUSDISPLAY_TERMINAL_TXT,-1);
  592.             ColumnLeft[2] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT,MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT,-1);
  593.             ColumnLeft[3] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_TIME_TXT,MSG_TERMSTATUSDISPLAY_ONLINE_TXT,-1);
  594.  
  595.             for(i = 0 ; ConfigStatus[i] ; i++)
  596.             {
  597.                 if((Len = SZ_BoxWidth(strlen(ConfigStatus[i]))) > Max)
  598.                     Max = Len;
  599.             }
  600.  
  601.             for(i = 0 ; ConfigBufferState[i] ; i++)
  602.             {
  603.                 if((Len = SZ_BoxWidth(strlen(ConfigBufferState[i]))) > Max)
  604.                     Max = Len;
  605.             }
  606.  
  607.             ColumnWidth[0] = Max;
  608.  
  609.             Max = SZ_BoxWidth(12);
  610.  
  611.             for(i = 0 ; ConfigEmulation[i] ; i++)
  612.             {
  613.                 if((Len = SZ_BoxWidth(strlen(ConfigEmulation[i]))) > Max)
  614.                     Max = Len;
  615.             }
  616.  
  617.             ColumnWidth[1] = Max;
  618.  
  619.             Max = SZ_BoxWidth(10);
  620.  
  621.             for(i = 0 ; ConfigParity[i] ; i++)
  622.             {
  623.                 if((Len = SZ_BoxWidth(4 + strlen(ConfigParity[i]))) > Max)
  624.                     Max = Len;
  625.             }
  626.  
  627.             ColumnWidth[2] = Max;
  628.  
  629.             ColumnWidth[3] = SZ_BoxWidth(8);
  630.  
  631.             FullWidth = 0;
  632.  
  633.             for(i = 0 ; i < 4 ; i++)
  634.                 FullWidth += ColumnWidth[i] + ColumnLeft[i];
  635.  
  636.             FullWidth += 3 * InterWidth;
  637.  
  638.             StatusInfo -> FullWidth        = FullWidth + 2 * SizeGadgetWidth;
  639.             StatusInfo -> FirstColumn    = ColumnLeft[0];
  640.  
  641.             if(FullWidth > LocalScreen -> Width)
  642.                 SZ_SetLeftEdge(ColumnLeft[0]);
  643.             else
  644.                 SZ_SetLeftEdge((LocalScreen -> Width - FullWidth) / 2 + ColumnLeft[0]);
  645.  
  646.             SZ_SetAbsoluteTop(2);
  647.             SZ_SetTopEdge(2);
  648.  
  649.             SZ_SetWidth(ColumnWidth[0]);
  650.  
  651.             StatusInfo -> BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&StatusInfo -> BoxList,
  652.                 SZ_Lines,    2,
  653.                 SZ_AutoWidth,    TRUE,
  654.             TAG_DONE);
  655.  
  656.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_STATUS_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_FONT_TXT),NULL);
  657.  
  658.             SZ_SetWidth(ColumnWidth[1]);
  659.             SZ_AddLeftOffset(ColumnLeft[1]);
  660.  
  661.             StatusInfo -> BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&StatusInfo -> BoxList,
  662.                 SZ_Lines,    2,
  663.                 SZ_AutoWidth,    TRUE,
  664.                 SZ_NewColumn,    TRUE,
  665.             TAG_DONE);
  666.  
  667.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_TERMINAL_TXT),NULL);
  668.  
  669.             SZ_SetWidth(ColumnWidth[2]);
  670.             SZ_AddLeftOffset(ColumnLeft[2]);
  671.  
  672.             StatusInfo -> BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&StatusInfo -> BoxList,
  673.                 SZ_Lines,    2,
  674.                 SZ_AutoWidth,    TRUE,
  675.                 SZ_NewColumn,    TRUE,
  676.             TAG_DONE);
  677.  
  678.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT),NULL);
  679.  
  680.             SZ_SetWidth(ColumnWidth[3]);
  681.             SZ_AddLeftOffset(ColumnLeft[3]);
  682.  
  683.             StatusInfo -> BoxArray[BoxCounter] = Box = SZ_CreateTextBox(&StatusInfo -> BoxList,
  684.                 SZ_Lines,    2,
  685.                 SZ_AutoWidth,    TRUE,
  686.                 SZ_NewColumn,    TRUE,
  687.             TAG_DONE);
  688.  
  689.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_TIME_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_ONLINE_TXT),NULL);
  690.  
  691.             if(!Box)
  692.             {
  693.                 SZ_FreeBoxes(StatusInfo -> BoxList);
  694.  
  695.                 DoSuperMethod(class,(Object *)NewGadget,OM_DISPOSE);
  696.  
  697.                 NewGadget = NULL;
  698.             }
  699.         }
  700.         else
  701.             StatusInfo -> FullWidth = SZ_BoxWidth(80) + 2 * SizeGadgetWidth;
  702.     }
  703.  
  704.     return((ULONG)NewGadget);
  705. }
  706.  
  707.     /* StatusGadgetDispatch():
  708.      *
  709.      *    Dispatch an object message.
  710.      */
  711.  
  712. STATIC ULONG __saveds __asm
  713. StatusGadgetDispatch(register __a0 struct IClass *class,register __a2 Object *object,register __a1 Msg msg)
  714. {
  715.     switch(msg -> MethodID)
  716.     {
  717.             /* Create new gadget. */
  718.  
  719.         case OM_NEW:
  720.  
  721.             return(NewStatusGadget(class,object,(struct opSet *)msg));
  722.  
  723.             /* Set attributes. */
  724.  
  725.         case OM_SET:
  726.  
  727.             return(SetStatusGadget(class,object,(struct opSet *)msg));
  728.  
  729.             /* Get attributes. */
  730.  
  731.         case OM_GET:
  732.  
  733.             return(GetStatusGadget(class,object,(struct opGet *)msg));
  734.  
  735.             /* Dispose gadget. */
  736.  
  737.         case OM_DISPOSE:
  738.  
  739.             return(DelStatusGadget(class,object,msg));
  740.  
  741.             /* Render the gadget. */
  742.  
  743.         case GM_RENDER:
  744.  
  745.             return(RenderStatusGadget(class,object,(struct gpRender *)msg));
  746.  
  747.             /* Do nothing. */
  748.  
  749.         case GM_HITTEST:
  750.  
  751.             return(0);
  752.  
  753.             /* Catchall... */
  754.  
  755.         default:
  756.  
  757.             return(DoSuperMethodA(class,object,msg));
  758.     }
  759. }
  760.  
  761.     /* FreeStatusGadgetClass():
  762.      *
  763.      *    Free the private status gadget class.
  764.      */
  765.  
  766. STATIC VOID
  767. FreeStatusGadgetClass()
  768. {
  769.     if(StatusGadgetClass)
  770.     {
  771.         FreeClass(StatusGadgetClass);
  772.  
  773.         StatusGadgetClass = NULL;
  774.     }
  775. }
  776.  
  777.     /* NewStatusGadgetClass():
  778.      *
  779.      *    Create a new status gadget class.
  780.      */
  781.  
  782. STATIC BYTE
  783. NewStatusGadgetClass()
  784. {
  785.         /* Release the old instance. */
  786.  
  787.     FreeStatusGadgetClass();
  788.  
  789.         /* Localize the title texts. */
  790.  
  791.     LocalizeString(ConfigBufferState,MSG_TERMSTATUSDISPLAY_FROZEN_TXT,MSG_TERMSTATUSDISPLAY_RECORDING_TXT);
  792.     LocalizeString(ConfigEmulation,MSG_TERMAUX_ANSI_VT102_TXT,MSG_TERMAUX_HEX_TXT);
  793.     LocalizeString(ConfigParity,MSG_TERMAUX_NONE_TXT,MSG_TERMAUX_SPACE_TXT);
  794.     LocalizeString(ConfigStatus,MSG_TERMAUX_READY_TXT,MSG_TERMAUX_HANG_UP_TXT);
  795.  
  796.         /* Create the class. */
  797.  
  798.     if(StatusGadgetClass = MakeClass(NULL,GADGETCLASS,NULL,sizeof(struct StatusInfo),0))
  799.     {
  800.             /* Install the dispatcher. */
  801.  
  802.         StatusGadgetClass -> cl_Dispatcher . h_Entry = (LONG (*)())StatusGadgetDispatch;
  803.  
  804.         return(TRUE);
  805.     }
  806.     else
  807.         return(FALSE);
  808. }
  809.  
  810.     /* DeleteStatusGadget(struct Gadget *Gadget):
  811.      *
  812.      *    Delete the status gadget.
  813.      */
  814.  
  815. VOID __regargs
  816. DeleteStatusGadget(struct Gadget *Gadget)
  817. {
  818.     DisposeObject(Gadget);
  819.  
  820.     FreeStatusGadgetClass();
  821. }
  822.  
  823.     /* CreateStatusGadget(LONG Width,LONG ID):
  824.      *
  825.      *    Create the status gadget.
  826.      */
  827.  
  828. struct Gadget * __regargs
  829. CreateStatusGadget(LONG Width,LONG ID)
  830. {
  831.         /* Create the new class. */
  832.  
  833.     if(NewStatusGadgetClass())
  834.     {
  835.         struct Gadget    *Gadget;
  836.         UBYTE         Mode;
  837.         LONG         Height;
  838.         struct Screen    *LocalScreen;
  839.  
  840.         if(SharedScreen)
  841.             LocalScreen = SharedScreen;
  842.         else
  843.             LocalScreen = DefaultPubScreen;
  844.  
  845.             /* Determine the mode of operation. */
  846.  
  847.         if(Config -> ScreenConfig -> StatusLine == STATUSLINE_COMPRESSED)
  848.             Mode = MODE_WB_COMPRESSED;
  849.         else
  850.             Mode = MODE_WB_NORMAL;
  851.  
  852.         SZ_SizeSetup(LocalScreen,&UserFont);
  853.  
  854.             /* Determine object height. */
  855.  
  856.         if(Mode == MODE_WB_NORMAL)
  857.             Height = 3 + SZ_BoxHeight(2);
  858.         else
  859.             Height = 2 + UserFontHeight;
  860.  
  861.             /* Create the new gadget. */
  862.  
  863.         if(Gadget = NewObject(StatusGadgetClass,NULL,
  864.             GA_ID,            ID,
  865.             GA_Left,        0,
  866.             GA_Width,        Width,
  867.             GA_Height,        Height,
  868.             GA_RelBottom,        -Height + 1,
  869.             GA_BottomBorder,    TRUE,
  870.             GA_Highlight,        GFLG_GADGHNONE,
  871.  
  872.             SGA_Mode,        Mode,
  873.         TAG_DONE))
  874.             return(Gadget);
  875.         else
  876.             FreeStatusGadgetClass();
  877.     }
  878.  
  879.     return(NULL);
  880. }
  881.  
  882.     /* DoStatusInfo(APTR Object,UBYTE Mode,UBYTE Type,STRPTR String):
  883.      *
  884.      *    Display information in the status line area.
  885.      */
  886.  
  887. STATIC VOID __regargs
  888. DoStatusInfo(APTR Object,UBYTE Mode,UBYTE Type,STRPTR String)
  889. {
  890.         /* What mode of operation is the status area in? */
  891.  
  892.     switch(Mode)
  893.     {
  894.             /* Uses the status gadget class. */
  895.  
  896.         case MODE_WB_NORMAL:
  897.         case MODE_WB_COMPRESSED:
  898.  
  899.             SetGadgetAttrs(Object,Window,NULL,
  900.                 SG_Status + Type,String,
  901.             TAG_DONE);
  902.  
  903.             break;
  904.  
  905.             /* Compressed mode. */
  906.  
  907.         case MODE_SCREEN_COMPRESSED:
  908.         {
  909.             struct RastPort *RPort = Object;
  910.  
  911.             STATIC BYTE Offsets[8] =
  912.             {
  913.                  0,
  914.                 -1,    /* Not supported */
  915.                 26,
  916.                 11,
  917.                 40,
  918.                 53,
  919.                 61,
  920.                 72
  921.             };
  922.  
  923.             STATIC UBYTE Strings[8][20];
  924.             UBYTE LineBuffer[90];
  925.             LONG i,j,k,Width;
  926.  
  927.             strcpy(Strings[Type],String);
  928.  
  929.             strcpy(LineBuffer,"         ·              ·             ·            ·       ·          ·         ");
  930.  
  931.             for(i = 0 ; i < 8 ; i++)
  932.             {
  933.                 if(Offsets[i] >= 0)
  934.                 {
  935.                     j = strlen(Strings[i]);
  936.  
  937.                     for(k = 0 ; k < j ; k++)
  938.                         LineBuffer[Offsets[i] + k] = Strings[i][k];
  939.                 }
  940.             }
  941.  
  942.             Width = TextLength(RPort,LineBuffer,80);
  943.  
  944.             if(StatusLineWidth && StatusLineWidth != Width)
  945.                 SetRast(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
  946.  
  947.             StatusLineWidth = Width;
  948.  
  949.             if(SharedScreen || DefaultPubScreen)
  950.                 Move(RPort,(StatusWindow -> GZZWidth - Width) / 2 + 1,1 + UserFontBase);
  951.             else
  952.                 Move(RPort,(StatusWindow -> Width - Width) / 2,UserFontBase);
  953.  
  954.             Text(RPort,LineBuffer,80);
  955.         }
  956.  
  957.         break;
  958.  
  959.             /* Normal mode. */
  960.  
  961.         case MODE_SCREEN_NORMAL:
  962.         {
  963.             STATIC UBYTE Codes[8][2] =
  964.             {
  965.                 STATUSBOX_STATUS_FONT,        0,
  966.                 STATUSBOX_STATUS_FONT,        1,
  967.  
  968.                 STATUSBOX_PROTOCOL_TERMINAL,    0,
  969.                 STATUSBOX_PROTOCOL_TERMINAL,    1,
  970.  
  971.                 STATUSBOX_RATE_PARAMETERS,    0,
  972.                 STATUSBOX_RATE_PARAMETERS,    1,
  973.  
  974.                 STATUSBOX_TIME_ONLINE,        0,
  975.                 STATUSBOX_TIME_ONLINE,        1
  976.             };
  977.  
  978.             struct ObjectCarrier *Carrier = (struct ObjectCarrier *)Object;
  979.  
  980.             SZ_PrintLine(Carrier -> RPort,Carrier -> BoxArray[Codes[Type][0]],Codes[Type][1],String);
  981.         }
  982.  
  983.         break;
  984.     }
  985. }
  986.  
  987.     /* DoInfo(APTR Object,UBYTE Mode,UBYTE Type,STRPTR String):
  988.      *
  989.      *    Post an update message to the status display server.
  990.      */
  991.  
  992. STATIC VOID __regargs
  993. DoInfo(APTR Object,UBYTE Mode,UBYTE Type,STRPTR String)
  994. {
  995.     struct UpdateMessage    *Msg;
  996.     WORD             Len = strlen(String) + 1;
  997.  
  998.         /* Allocate enough space to hold both the string
  999.          * and the message.
  1000.          */
  1001.  
  1002.     if(Msg = (struct UpdateMessage *)AllocVecPooled(sizeof(struct UpdateMessage) + Len,MEMF_ANY | MEMF_PUBLIC | MEMF_CLEAR))
  1003.     {
  1004.             /* Fill in the message head. */
  1005.  
  1006.         Msg -> VanillaMessage . mn_Length = sizeof(struct UpdateMessage) + Len;
  1007.  
  1008.             /* Set up the name pointer. */
  1009.  
  1010.         Msg -> VanillaMessage . mn_Node . ln_Name = (STRPTR)(Msg + 1);
  1011.  
  1012.             /* Copy the string. */
  1013.  
  1014.         strcpy(Msg -> VanillaMessage . mn_Node . ln_Name,String);
  1015.  
  1016.             /* Fill in the remaining data. */
  1017.  
  1018.         Msg -> Object    = Object;
  1019.         Msg -> Mode    = Mode;
  1020.         Msg -> Type    = Type;
  1021.  
  1022.             /* Post the message. */
  1023.  
  1024.         PutMsg(StatusDisplayPort,(struct Message *)Msg);
  1025.     }
  1026. }
  1027.  
  1028.     /* UpdateInfo(APTR Object,UBYTE Mode,UBYTE Type,...):
  1029.      *
  1030.      *    Update the information displayed in the status
  1031.      *    area.
  1032.      */
  1033.  
  1034. STATIC VOID __stdargs
  1035. UpdateInfo(APTR Object,UBYTE Mode,UBYTE Type,...)
  1036. {
  1037.     if(Object)
  1038.     {
  1039.         UBYTE     MiniBuffer[50];
  1040.         STRPTR    *String;
  1041.         LONG    *Numeral;
  1042.         va_list     VarArgs;
  1043.  
  1044.         va_start(VarArgs,Type);
  1045.  
  1046.         String    = (STRPTR *)VarArgs;
  1047.         Numeral    = (LONG *)VarArgs;
  1048.  
  1049.         switch(Type)
  1050.         {
  1051.             case INFO_STATUS:
  1052.  
  1053.                 strcpy(MiniBuffer,ConfigStatus[Numeral[0]]);
  1054.                 strcat(MiniBuffer,"         ");
  1055.  
  1056.                 MiniBuffer[9] = 0;
  1057.  
  1058.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1059.  
  1060.                 break;
  1061.  
  1062.             case INFO_BUFFER:
  1063.  
  1064.                 if(Mode == MODE_SCREEN_NORMAL || Mode == MODE_WB_NORMAL)
  1065.                     DoInfo(Object,Mode,Type,ConfigBufferState[Numeral[0]]);
  1066.  
  1067.                 break;
  1068.  
  1069.             case INFO_ONLINECOST:
  1070.  
  1071.                 strcpy(MiniBuffer,String[0]);
  1072.                 strcat(MiniBuffer,"          ");
  1073.  
  1074.                 MiniBuffer[8] = 0;
  1075.  
  1076.                 DoInfo(Object,Mode,INFO_ONLINETIME,MiniBuffer);
  1077.  
  1078.                 break;
  1079.  
  1080.             case INFO_CURRENTTIME:
  1081.  
  1082.                 FormatTime(MiniBuffer,Numeral[0],Numeral[1],Numeral[2]);
  1083.  
  1084.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1085.  
  1086.                 break;
  1087.  
  1088.             case INFO_ONLINETIME:
  1089.  
  1090.                 SPrintf(MiniBuffer,"%02ld:%02ld:%02ld",Numeral[0],Numeral[1],Numeral[2]);
  1091.  
  1092.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1093.  
  1094.                 break;
  1095.  
  1096.             case INFO_BAUDRATE:
  1097.  
  1098.                 if(LocaleBase)
  1099.                     SPrintf(MiniBuffer,"%lD        ",Numeral[0]);
  1100.                 else
  1101.                     SPrintf(MiniBuffer,"%ld        ",Numeral[0]);
  1102.  
  1103.                 MiniBuffer[7] = 0;
  1104.  
  1105.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1106.  
  1107.                 break;
  1108.  
  1109.             case INFO_PROTOCOL:
  1110.             case INFO_EMULATION:
  1111.  
  1112.                 strcpy(MiniBuffer,String[0]);
  1113.  
  1114.                 strcat(MiniBuffer,"           ");
  1115.  
  1116.                 MiniBuffer[12] = 0;
  1117.  
  1118.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1119.  
  1120.                 break;
  1121.  
  1122.             case INFO_PARAMETERS:
  1123.  
  1124.                 if(Mode == MODE_SCREEN_COMPRESSED || Mode == MODE_WB_COMPRESSED)
  1125.                 {
  1126.                     STATIC UBYTE Parities[5] =
  1127.                     {
  1128.                         'N','E','O','M','S'
  1129.                     };
  1130.  
  1131.                     SPrintf(MiniBuffer,"%ld-%lc-%ld",Numeral[0],Parities[Numeral[1]],Numeral[2]);
  1132.                 }
  1133.                 else
  1134.                     SPrintf(MiniBuffer,"%ld-%s-%ld",Numeral[0],ConfigParity[Numeral[1]],Numeral[2]);
  1135.  
  1136.                 DoInfo(Object,Mode,Type,MiniBuffer);
  1137.  
  1138.                 break;
  1139.         }
  1140.  
  1141.         va_end(VarArgs);
  1142.     }
  1143. }
  1144.  
  1145.     /* Raise(UWORD Colour):
  1146.      *
  1147.      *    Make an RGB value brighter.
  1148.      */
  1149.  
  1150. STATIC UWORD __inline
  1151. Raise(UWORD Colour)
  1152. {
  1153.     UWORD R,G,B;
  1154.  
  1155.     R =  (Colour >> 8)        + 4;
  1156.     G = ((Colour >> 4) & 0xF) + 4;
  1157.     B = ((Colour     ) & 0xF) + 4;
  1158.  
  1159.     if(R > 15)
  1160.         R = 15;
  1161.  
  1162.     if(G > 15)
  1163.         G = 15;
  1164.  
  1165.     if(B > 15)
  1166.         B = 15;
  1167.  
  1168.     return((UWORD)(R << 8 | G << 4 | B));
  1169. }
  1170.  
  1171.     /* VisualBeep():
  1172.      *
  1173.      *    Handle the visual part of the display beep.
  1174.      */
  1175.  
  1176. STATIC BYTE
  1177. VisualBeep(VOID)
  1178. {
  1179.     struct UCopList    *UserCopperList;
  1180.  
  1181.         /* Create a user copper list. */
  1182.  
  1183.     if(UserCopperList = (struct UCopList *)AllocMem(sizeof(struct UCopList),MEMF_ANY|MEMF_CLEAR))
  1184.     {
  1185.             /* Initialize for 35 commands. */
  1186.  
  1187.         if(UCopperListInit(UserCopperList,1 + 16 + 1 + 16 + 1))
  1188.         {
  1189.             WORD i;
  1190.  
  1191.                 /* Wait until first line of window. */
  1192.  
  1193.             CWAIT(UserCopperList,Window -> TopEdge,0);
  1194.  
  1195.                 /* Set the light colours. */
  1196.  
  1197.             for(i = 0 ; i < 16 ; i++)
  1198.                 CMOVE(UserCopperList,custom . color[i],Raise(GetRGB4(Screen -> ViewPort . ColorMap,i)));
  1199.  
  1200.                 /* Wait until bottom of window. */
  1201.  
  1202.             CWAIT(UserCopperList,Window -> TopEdge + Window -> Height - 1,0);
  1203.  
  1204.                 /* Set the standard colours. */
  1205.  
  1206.             for(i = 0 ; i < 16 ; i++)
  1207.                 CMOVE(UserCopperList,custom . color[i],GetRGB4(Screen -> ViewPort . ColorMap,i));
  1208.  
  1209.                 /* Finish list. */
  1210.  
  1211.             CEND(UserCopperList);
  1212.  
  1213.                 /* Install user copper list... */
  1214.  
  1215.             Screen -> ViewPort . UCopIns = UserCopperList;
  1216.  
  1217.                 /* ...and display it. */
  1218.  
  1219.             RethinkDisplay();
  1220.  
  1221.             return(TRUE);
  1222.         }
  1223.         else
  1224.             FreeMem(UserCopperList,sizeof(struct UCopList));
  1225.     }
  1226.  
  1227.     return(FALSE);
  1228. }
  1229.  
  1230.     /* StatusDisplayServer(VOID):
  1231.      *
  1232.      *    Yet another asynchronous background task to display
  1233.      *    some information.
  1234.      */
  1235.  
  1236. STATIC VOID __saveds
  1237. StatusDisplayServer(VOID)
  1238. {
  1239.         /* Create the interface port. */
  1240.  
  1241.     if(StatusDisplayPort = CreateMsgPort())
  1242.     {
  1243.         struct UpdateMessage    *Msg;
  1244.         ULONG             Signals;
  1245.  
  1246.             /* Ring back... */
  1247.  
  1248.         Signal(StatusProcess,SIG_HANDSHAKE);
  1249.  
  1250.             /* Wait for messages or termination signal. */
  1251.  
  1252.         FOREVER
  1253.         {
  1254.             Signals = Wait(SIG_KILL | PORTMASK(StatusDisplayPort));
  1255.  
  1256.                 /* Termination? */
  1257.  
  1258.             if(Signals & SIG_KILL)
  1259.                 break;
  1260.  
  1261.                 /* Message arrival? */
  1262.  
  1263.             if(Signals & PORTMASK(StatusDisplayPort))
  1264.             {
  1265.                     /* Process all pending messages. */
  1266.  
  1267.                 while(Msg = (struct UpdateMessage *)GetMsg(StatusDisplayPort))
  1268.                 {
  1269.                     DoStatusInfo(Msg -> Object,Msg -> Mode,Msg -> Type,Msg -> VanillaMessage . mn_Node . ln_Name);
  1270.  
  1271.                     FreeVecPooled(Msg);
  1272.                 }
  1273.             }
  1274.         }
  1275.  
  1276.             /* Remove all pending messages. */
  1277.  
  1278.         while(Msg = (struct UpdateMessage *)GetMsg(StatusDisplayPort))
  1279.             FreeVecPooled(Msg);
  1280.  
  1281.             /* Remove the msgport. */
  1282.  
  1283.         DeleteMsgPort(StatusDisplayPort);
  1284.     }
  1285.  
  1286.         /* Lock & quit... */
  1287.  
  1288.     Forbid();
  1289.  
  1290.     Signal(StatusProcess,SIG_HANDSHAKE);
  1291.  
  1292.     RemTask(StatusDisplayTask = NULL);
  1293. }
  1294.  
  1295.     /* StatusServer():
  1296.      *
  1297.      *    Asynchronous process to continuosly display the current
  1298.      *    terminal settings.
  1299.      */
  1300.  
  1301. VOID __saveds
  1302. StatusServer()
  1303. {
  1304.     STATIC struct timeval     OnlineTime,
  1305.                  LastTime,
  1306.                  TempTime;
  1307.     STATIC BYTE         GotOnline        = FALSE,
  1308.                  WasOnline        = FALSE,
  1309.                  ShowPay        = FALSE,
  1310.                  FlagBit        = FALSE;
  1311.     STATIC LONG         SecCount        = 0,
  1312.                  MinCount        = 0,
  1313.                  BeepCount        = 0;
  1314.  
  1315.     struct TextBox        *BoxArray[4],
  1316.                 *BoxList = NULL,
  1317.                 *Box;
  1318.  
  1319.     struct RastPort        *RPort;
  1320.  
  1321.     APTR             SomeObject;
  1322.     struct ObjectCarrier     Carrier;
  1323.  
  1324.     struct timerequest    *StatusTimeRequest;
  1325.     struct MsgPort        *StatusTimePort;
  1326.  
  1327.     BYTE             Background        = FALSE,
  1328.                  FlashIt        = FALSE,
  1329.                  SetColours        = FALSE,
  1330.                  StandardColours    = TRUE,
  1331.                  KeepGoing        = TRUE,
  1332.                  Beeping        = FALSE,
  1333.                  StatusMode        = Config -> ScreenConfig -> StatusLine;
  1334.  
  1335.     BYTE             LastProtocol[40],
  1336.                  ProtocolBuffer[40],
  1337.                  LastEmulationName[40];
  1338.  
  1339.     BYTE             LastFrozen        = -1,
  1340.                  LastEmulation        = -1,
  1341.                  LastBitsPerChar    = -1,
  1342.                  LastParity        = -1,
  1343.                  LastStopBits        = -1,
  1344.                  LastStatus        = -1;
  1345.  
  1346.     LONG             LastBaud        = -1;
  1347.  
  1348.     LONG             i,
  1349.                  ThisHour,
  1350.                  ThisMinute,
  1351.                  BoxCounter = 0,
  1352.                  FullWidth;
  1353.     WORD             ColumnLeft[4],
  1354.                  ColumnWidth[4],
  1355.                  Max,
  1356.                  Len;
  1357.     BYTE             AllFine = TRUE;
  1358.     UBYTE             Mode;
  1359.  
  1360.     StatusLineWidth = 0;
  1361.  
  1362.     LastProtocol[0] = 0;
  1363.  
  1364.     LastEmulationName[0] = 0;
  1365.  
  1366.     LocalizeString(ConfigBufferState,MSG_TERMSTATUSDISPLAY_FROZEN_TXT,MSG_TERMSTATUSDISPLAY_RECORDING_TXT);
  1367.     LocalizeString(ConfigEmulation,MSG_TERMAUX_ANSI_VT102_TXT,MSG_TERMAUX_HEX_TXT);
  1368.     LocalizeString(ConfigParity,MSG_TERMAUX_NONE_TXT,MSG_TERMAUX_SPACE_TXT);
  1369.     LocalizeString(ConfigStatus,MSG_TERMAUX_READY_TXT,MSG_TERMAUX_RECORD_LINE_TXT);
  1370.  
  1371.     if(StatusWindow)
  1372.     {
  1373.         RPort = StatusWindow -> RPort;
  1374.  
  1375.         SetRast(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  1376.  
  1377.             /* Render the information. */
  1378.  
  1379.         SZ_SizeSetup(StatusWindow -> WScreen,&UserFont);
  1380.  
  1381.         if(StatusMode == STATUSLINE_COMPRESSED)
  1382.         {
  1383.             StatusOffset = (StatusWindow -> Width - StatusWindow -> BorderLeft - StatusWindow -> BorderRight - 80 * UserFontWidth) / 2;
  1384.  
  1385.             SetAPen(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
  1386.  
  1387.             RectFill(RPort,0,0,StatusWindow -> Width - 1,StatusWindow -> Height - 1);
  1388.  
  1389.             SetDrMd(RPort,JAM2);
  1390.             SetAPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  1391.             SetBPen(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
  1392.  
  1393.             SetFont(RPort,UserTextFont);
  1394.         }
  1395.         else
  1396.         {
  1397.             SetBPen(RPort,DrawInfo -> dri_Pens[BACKGROUNDPEN]);
  1398.  
  1399.                 /* Draw a separating line. */
  1400.  
  1401.             if(!Config -> ScreenConfig -> SplitStatus)
  1402.             {
  1403.                 SetAPen(RPort,DrawInfo -> dri_Pens[SHADOWPEN]);
  1404.                 Move(RPort,0,0);
  1405.                 Draw(RPort,StatusWindow -> Width - 1,0);
  1406.  
  1407.                 SetAPen(RPort,DrawInfo -> dri_Pens[SHINEPEN]);
  1408.                 Move(RPort,0,1);
  1409.                 Draw(RPort,StatusWindow -> Width - 1,1);
  1410.             }
  1411.  
  1412.             SetAPen(RPort,DrawInfo -> dri_Pens[TEXTPEN]);
  1413.  
  1414.             ColumnLeft[0] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_STATUS_TXT,MSG_TERMSTATUSDISPLAY_FONT_TXT,-1);
  1415.             ColumnLeft[1] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT,MSG_TERMSTATUSDISPLAY_TERMINAL_TXT,-1);
  1416.             ColumnLeft[2] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT,MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT,-1);
  1417.             ColumnLeft[3] = SZ_LeftOffsetN(MSG_TERMSTATUSDISPLAY_TIME_TXT,MSG_TERMSTATUSDISPLAY_ONLINE_TXT,-1);
  1418.  
  1419.             Max = 0;
  1420.  
  1421.             for(i = 0 ; ConfigStatus[i] ; i++)
  1422.             {
  1423.                 if((Len = SZ_BoxWidth(strlen(ConfigStatus[i]))) > Max)
  1424.                     Max = Len;
  1425.             }
  1426.  
  1427.             for(i = 0 ; ConfigBufferState[i] ; i++)
  1428.             {
  1429.                 if((Len = SZ_BoxWidth(strlen(ConfigBufferState[i]))) > Max)
  1430.                     Max = Len;
  1431.             }
  1432.  
  1433.             ColumnWidth[0] = Max;
  1434.  
  1435.             Max = SZ_BoxWidth(12);
  1436.  
  1437.             for(i = 0 ; ConfigEmulation[i] ; i++)
  1438.             {
  1439.                 if((Len = SZ_BoxWidth(strlen(ConfigEmulation[i]))) > Max)
  1440.                     Max = Len;
  1441.             }
  1442.  
  1443.             ColumnWidth[1] = Max;
  1444.  
  1445.             Max = SZ_BoxWidth(10);
  1446.  
  1447.             for(i = 0 ; ConfigParity[i] ; i++)
  1448.             {
  1449.                 if((Len = SZ_BoxWidth(4 + strlen(ConfigParity[i]))) > Max)
  1450.                     Max = Len;
  1451.             }
  1452.  
  1453.             ColumnWidth[2] = Max;
  1454.  
  1455.             ColumnWidth[3] = SZ_BoxWidth(8);
  1456.  
  1457.             FullWidth = 0;
  1458.  
  1459.             for(i = 0 ; i < 4 ; i++)
  1460.                 FullWidth += ColumnWidth[i] + ColumnLeft[i];
  1461.  
  1462.             FullWidth += 3 * InterWidth;
  1463.  
  1464.             if(!Config -> ScreenConfig -> SplitStatus)
  1465.             {
  1466.                 if(FullWidth > Screen -> Width)
  1467.                     SZ_SetLeftEdge(ColumnLeft[0]);
  1468.                 else
  1469.                     SZ_SetLeftEdge((Screen -> Width - FullWidth) / 2 + ColumnLeft[0]);
  1470.  
  1471.                 SZ_SetAbsoluteTop(3);
  1472.                 SZ_SetTopEdge(3);
  1473.             }
  1474.             else
  1475.             {
  1476.                 SZ_SetLeftEdge(ColumnLeft[0] + 1);
  1477.  
  1478.                 SZ_SetAbsoluteTop(1);
  1479.                 SZ_SetTopEdge(1);
  1480.             }
  1481.  
  1482.             SZ_SetWidth(ColumnWidth[0]);
  1483.  
  1484.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  1485.                 SZ_Lines,    2,
  1486.                 SZ_AutoWidth,    TRUE,
  1487.             TAG_DONE);
  1488.  
  1489.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_STATUS_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_FONT_TXT),NULL);
  1490.  
  1491.             SZ_SetWidth(ColumnWidth[1]);
  1492.             SZ_AddLeftOffset(ColumnLeft[1]);
  1493.  
  1494.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  1495.                 SZ_Lines,    2,
  1496.                 SZ_AutoWidth,    TRUE,
  1497.                 SZ_NewColumn,    TRUE,
  1498.             TAG_DONE);
  1499.  
  1500.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_PROTOCOL_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_TERMINAL_TXT),NULL);
  1501.  
  1502.             SZ_SetWidth(ColumnWidth[2]);
  1503.             SZ_AddLeftOffset(ColumnLeft[2]);
  1504.  
  1505.             BoxArray[BoxCounter++] = Box = SZ_CreateTextBox(&BoxList,
  1506.                 SZ_Lines,    2,
  1507.                 SZ_AutoWidth,    TRUE,
  1508.                 SZ_NewColumn,    TRUE,
  1509.             TAG_DONE);
  1510.  
  1511.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_BAUDRATE_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_PARAMETERS_TXT),NULL);
  1512.  
  1513.             SZ_SetWidth(ColumnWidth[3]);
  1514.             SZ_AddLeftOffset(ColumnLeft[3]);
  1515.  
  1516.             BoxArray[BoxCounter] = Box = SZ_CreateTextBox(&BoxList,
  1517.                 SZ_Lines,    2,
  1518.                 SZ_AutoWidth,    TRUE,
  1519.                 SZ_NewColumn,    TRUE,
  1520.             TAG_DONE);
  1521.  
  1522.             SZ_SetBoxTitles(Box,LocaleString(MSG_TERMSTATUSDISPLAY_TIME_TXT),LocaleString(MSG_TERMSTATUSDISPLAY_ONLINE_TXT),NULL);
  1523.  
  1524.             if(!Box)
  1525.                 AllFine = FALSE;
  1526.             else
  1527.                 SZ_DrawBoxes(RPort,BoxList);
  1528.         }
  1529.     }
  1530.     else
  1531.     {
  1532.         if((Config -> ScreenConfig -> UseWorkbench || SharedScreen) && StatusGadget)
  1533.             AllFine = TRUE;
  1534.     }
  1535.  
  1536.         /* Everything fine so far? */
  1537.  
  1538.     if(AllFine)
  1539.     {
  1540.         Forbid();
  1541.  
  1542.             /* Create the display server task. */
  1543.  
  1544.         if(StatusDisplayTask = CreateTask("term Status Display Task",5,StatusDisplayServer,4000))
  1545.         {
  1546.             ClrSignal(SIG_HANDSHAKE);
  1547.  
  1548.             Wait(SIG_HANDSHAKE);
  1549.         }
  1550.  
  1551.         Permit();
  1552.     }
  1553.  
  1554.         /* Is the display server task up and running? */
  1555.  
  1556.     if(StatusDisplayTask)
  1557.     {
  1558.             /* Create a timer device request. */
  1559.  
  1560.         if(StatusTimePort = (struct MsgPort *)CreateMsgPort())
  1561.         {
  1562.             if(StatusTimeRequest = (struct timerequest *)CreateIORequest(StatusTimePort,sizeof(struct timerequest)))
  1563.             {
  1564.                 if(!OpenDevice(TIMERNAME,UNIT_VBLANK,StatusTimeRequest,0))
  1565.                 {
  1566.                         /* Signal our father process
  1567.                          * that we're running.
  1568.                          */
  1569.  
  1570.                     Signal(ThisProcess,SIG_HANDSHAKE);
  1571.  
  1572.                     if(StatusWindow)
  1573.                     {
  1574.                         if(StatusMode == STATUSLINE_COMPRESSED)
  1575.                         {
  1576.                             Mode = MODE_SCREEN_COMPRESSED;
  1577.  
  1578.                             SomeObject = RPort;
  1579.                         }
  1580.                         else
  1581.                         {
  1582.                             Mode = MODE_SCREEN_NORMAL;
  1583.  
  1584.                             Carrier . RPort        = RPort;
  1585.                             Carrier . BoxArray    = BoxArray;
  1586.  
  1587.                             SomeObject = &Carrier;
  1588.                         }
  1589.  
  1590.                         UpdateInfo(SomeObject,Mode,INFO_ONLINETIME,0,0,0);
  1591.                     }
  1592.                     else
  1593.                     {
  1594.                         if(StatusGadget)
  1595.                         {
  1596.                             SomeObject = StatusGadget;
  1597.  
  1598.                             if(StatusMode == STATUSLINE_COMPRESSED)
  1599.                                 Mode = MODE_WB_COMPRESSED;
  1600.                             else
  1601.                                 Mode = MODE_WB_NORMAL;
  1602.  
  1603.                             UpdateInfo(SomeObject,Mode,INFO_ONLINETIME,0,0,0);
  1604.                         }
  1605.                         else
  1606.                             SomeObject = NULL;
  1607.                     }
  1608.  
  1609.                         /* Keep on displaying. */
  1610.  
  1611.                     while(KeepGoing)
  1612.                     {
  1613.                             /* Are we to quit? */
  1614.  
  1615.                         if(CheckSignal(SIG_KILL))
  1616.                             KeepGoing = FALSE;
  1617.  
  1618.                             /* Get the current time. */
  1619.  
  1620.                         StatusTimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  1621.  
  1622.                         DoIO(StatusTimeRequest);
  1623.  
  1624.                             /* A connection has just
  1625.                              * been established.
  1626.                              */
  1627.  
  1628.                         if(Online && !GotOnline)
  1629.                         {
  1630.                             OnlineTime = StatusTimeRequest -> tr_time;
  1631.  
  1632.                                 /* Add up connection time. */
  1633.  
  1634.                             if(OnlinePlus)
  1635.                             {
  1636.                                 struct timeval GetBack;
  1637.  
  1638.                                 GetBack . tv_secs    = (OnlinePlus / 6) * 60 + (OnlinePlus % 6) * 10;
  1639.                                 GetBack . tv_micro    = 0;
  1640.  
  1641.                                 OnlinePlus = 0;
  1642.  
  1643.                                 SubTime(&OnlineTime,&GetBack);
  1644.                             }
  1645.  
  1646.                             GotOnline = TRUE;
  1647.  
  1648.                             SecCount = 0;
  1649.  
  1650.                             FlagBit = FALSE;
  1651.                         }
  1652.  
  1653.                             /* Print the current time. */
  1654.  
  1655.                         ThisHour    = (StatusTimeRequest -> tr_time . tv_secs % 86400) / 3600;
  1656.                         ThisMinute    = (StatusTimeRequest -> tr_time . tv_secs % 3600) / 60;
  1657.  
  1658.                         UpdateInfo(SomeObject,Mode,INFO_CURRENTTIME,ThisHour,ThisMinute,StatusTimeRequest -> tr_time . tv_secs % 60);
  1659.  
  1660.                             /* Handle routine checkup actions. */
  1661.  
  1662.                         if(!(SecCount & 1))
  1663.                             Signal(ThisProcess,SIG_CHECK);
  1664.  
  1665.                         if(Online)
  1666.                         {
  1667.                             WasOnline = TRUE;
  1668.  
  1669.                             if(ChosenEntry)
  1670.                             {
  1671.                                 if(!(ThisMinute % 10) && !(StatusTimeRequest -> tr_time . tv_secs % 60))
  1672.                                 {
  1673.                                     ChosenInUse = TRUE;
  1674.  
  1675.                                     SelectTime(ChosenEntry);
  1676.  
  1677.                                     ChosenInUse = FALSE;
  1678.                                 }
  1679.  
  1680.                                 if(!CurrentPay)
  1681.                                     CurrentPay = PayPerUnit[DT_FIRST_UNIT];
  1682.  
  1683.                                 FlagBit ^= TRUE;
  1684.  
  1685.                                 if(!FlagBit)
  1686.                                 {
  1687.                                     if(SecPerUnit[WhichUnit] && SecCount == SecPerUnit[WhichUnit])
  1688.                                     {
  1689.                                         SecCount = 0;
  1690.  
  1691.                                         WhichUnit = DT_NEXT_UNIT;
  1692.  
  1693.                                         CurrentPay += PayPerUnit[DT_NEXT_UNIT];
  1694.                                     }
  1695.  
  1696.                                     SecCount++;
  1697.                                 }
  1698.                             }
  1699.  
  1700.                                 /* Show the time
  1701.                                  * we have been online
  1702.                                  * yet.
  1703.                                  */
  1704.  
  1705.                             TempTime = StatusTimeRequest -> tr_time;
  1706.  
  1707.                             SubTime(&TempTime,&OnlineTime);
  1708.  
  1709.                             if(StatusTimeRequest -> tr_time . tv_secs != LastTime . tv_secs)
  1710.                             {
  1711.                                 LastTime = StatusTimeRequest -> tr_time;
  1712.  
  1713.                                 switch(Config -> ScreenConfig -> TimeMode)
  1714.                                 {
  1715.                                     case ONLINETIME_TIME:    ShowPay = FALSE;
  1716.                                                 break;
  1717.  
  1718.                                     case ONLINETIME_COST:    ShowPay = TRUE;
  1719.                                                 break;
  1720.  
  1721.                                     case ONLINETIME_BOTH:    if(TempTime . tv_secs && !(TempTime . tv_secs % 5))
  1722.                                                     ShowPay ^= TRUE;
  1723.  
  1724.                                                 break;
  1725.                                 }
  1726.  
  1727.                                 if(ShowPay && ChosenEntry)
  1728.                                     UpdateInfo(SomeObject,Mode,INFO_ONLINECOST,CreateSum(CurrentPay,FALSE));
  1729.                                 else
  1730.                                     UpdateInfo(SomeObject,Mode,INFO_ONLINETIME,(TempTime . tv_secs % 86400) / 3600,(TempTime . tv_secs % 3600) / 60,TempTime . tv_secs % 60);
  1731.  
  1732.                                 OnlineMinutes = TempTime . tv_secs / 60;
  1733.                             }
  1734.                         }
  1735.                         else
  1736.                         {
  1737.                             if(WasOnline)
  1738.                             {
  1739.                                 WasOnline = FALSE;
  1740.  
  1741.                                 UpdateInfo(SomeObject,Mode,INFO_ONLINETIME,(TempTime . tv_secs % 86400) / 3600,(TempTime . tv_secs % 3600) / 60,TempTime . tv_secs % 60);
  1742.                             }
  1743.  
  1744.                             if(GotOnline)
  1745.                                 GotOnline = FALSE;
  1746.                         }
  1747.  
  1748.                             /* Take care of the visual beep
  1749.                              * if enabled.
  1750.                              */
  1751.  
  1752.                         if(Beeping)
  1753.                         {
  1754.                             if(!(BeepCount--))
  1755.                             {
  1756.                                 Beeping = FALSE;
  1757.  
  1758.                                     /* Remove the copper list. */
  1759.  
  1760.                                 FreeVPortCopLists(&Screen -> ViewPort);
  1761.  
  1762.                                     /* Really remove it. */
  1763.  
  1764.                                 RemakeDisplay();
  1765.  
  1766.                                     /* Clear the signal bit. */
  1767.  
  1768.                                 ClrSignal(SIG_BELL);
  1769.                             }
  1770.                         }
  1771.  
  1772.                             /* Are we to show a visual beep? */
  1773.  
  1774.                         if(CheckSignal(SIG_BELL))
  1775.                         {
  1776.                             if(Config -> TerminalConfig -> BellMode == BELL_SYSTEM)
  1777.                                 DisplayBeep(Window -> WScreen);
  1778.                             else
  1779.                             {
  1780.                                 if(Screen && !Config -> ScreenConfig -> UseWorkbench && !Beeping && (Config -> TerminalConfig -> BellMode == BELL_VISIBLE || Config -> TerminalConfig -> BellMode == BELL_BOTH))
  1781.                                 {
  1782.                                     if(VisualBeep())
  1783.                                     {
  1784.                                         Beeping = TRUE;
  1785.  
  1786.                                         BeepCount = 1;
  1787.                                     }
  1788.                                 }
  1789.                             }
  1790.                         }
  1791.  
  1792.                             /* Display the current terminal
  1793.                              * status.
  1794.                              */
  1795.  
  1796.                         if(LastStatus != Status)
  1797.                             UpdateInfo(SomeObject,Mode,INFO_STATUS,LastStatus = Status);
  1798.  
  1799.                             /* Show the current transfer
  1800.                              * protocol.
  1801.                              */
  1802.  
  1803.                         if(strcmp(LastProtocol,FilePart(LastXprLibrary)))
  1804.                         {
  1805.                             strcpy(LastProtocol,FilePart(LastXprLibrary));
  1806.  
  1807.                             if((Len = strlen(LastProtocol)) > 3)
  1808.                             {
  1809.                                 strcpy(ProtocolBuffer,&LastProtocol[3]);
  1810.  
  1811.                                 for(i = 0 ; i < Len - 3 ; i++)
  1812.                                 {
  1813.                                     if(ProtocolBuffer[i] == '.')
  1814.                                     {
  1815.                                         ProtocolBuffer[i] = 0;
  1816.  
  1817.                                         break;
  1818.                                     }
  1819.                                 }
  1820.  
  1821.                                 ProtocolBuffer[0] = ToUpper(ProtocolBuffer[0]);
  1822.  
  1823.                                 UpdateInfo(SomeObject,Mode,INFO_PROTOCOL,ProtocolBuffer);
  1824.                             }
  1825.                         }
  1826.  
  1827.                             /* Show the current baud
  1828.                              * rate.
  1829.                              */
  1830.  
  1831.                         if(LastBaud != Config -> SerialConfig -> BaudRate)
  1832.                             UpdateInfo(SomeObject,Mode,INFO_BAUDRATE,LastBaud = Config -> SerialConfig -> BaudRate);
  1833.  
  1834.                             /* Show the current
  1835.                              * terminal font.
  1836.                              */
  1837.  
  1838.                         if(LastFrozen != BufferFrozen)
  1839.                         {
  1840.                             LastFrozen = BufferFrozen;
  1841.  
  1842.                             UpdateInfo(SomeObject,Mode,INFO_BUFFER,LastFrozen != TRUE);
  1843.                         }
  1844.  
  1845.                             /* Show the current terminal
  1846.                              * emulation.
  1847.                              */
  1848.  
  1849.                         if(LastEmulation != Config -> TerminalConfig -> EmulationMode || (Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL && Stricmp(EmulationName,LastEmulationName)))
  1850.                         {
  1851.                             LastEmulation = Config -> TerminalConfig -> EmulationMode;
  1852.  
  1853.                             if(Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  1854.                             {
  1855.                                 UpdateInfo(SomeObject,Mode,INFO_EMULATION,EmulationName);
  1856.  
  1857.                                 strcpy(LastEmulationName,EmulationName);
  1858.                             }
  1859.                             else
  1860.                                 UpdateInfo(SomeObject,Mode,INFO_EMULATION,ConfigEmulation[LastEmulation]);
  1861.                         }
  1862.  
  1863.                             /* Show the current serial
  1864.                              * parameters (parity, etc).
  1865.                              */
  1866.  
  1867.                         if(LastBitsPerChar != Config -> SerialConfig -> BitsPerChar || LastParity != Config -> SerialConfig -> Parity || LastStopBits != Config -> SerialConfig -> StopBits)
  1868.                         {
  1869.                             LastBitsPerChar    = Config -> SerialConfig -> BitsPerChar;
  1870.                             LastParity    = Config -> SerialConfig -> Parity;
  1871.                             LastStopBits    = Config -> SerialConfig -> StopBits;
  1872.  
  1873.                             UpdateInfo(SomeObject,Mode,INFO_PARAMETERS,LastBitsPerChar,LastParity,LastStopBits);
  1874.                         }
  1875.  
  1876.                             /* Wait another half a second. */
  1877.  
  1878.                         if(KeepGoing)
  1879.                         {
  1880.                             ULONG    Mask;
  1881.                             BOOLEAN    ResetTime = FALSE;
  1882.  
  1883.                             StatusTimeRequest -> tr_node . io_Command    = TR_ADDREQUEST;
  1884.                             StatusTimeRequest -> tr_time . tv_secs        = 0;
  1885.                             StatusTimeRequest -> tr_time . tv_micro        = MILLION / 2;
  1886.  
  1887.                             SendIO(StatusTimeRequest);
  1888.  
  1889.                             FOREVER
  1890.                             {
  1891.                                 Mask = Wait(SIG_BELL | PORTMASK(StatusTimePort) | SIG_CLOSEWINDOW | SIG_RESETTIME);
  1892.  
  1893.                                     /* Close the window and keep quiet? */
  1894.  
  1895.                                 if(Mask & SIG_CLOSEWINDOW)
  1896.                                 {
  1897.                                     Forbid();
  1898.  
  1899.                                     if(StatusDisplayTask)
  1900.                                     {
  1901.                                         Signal(StatusDisplayTask,SIG_KILL);
  1902.  
  1903.                                         ClrSignal(SIG_HANDSHAKE);
  1904.  
  1905.                                         Wait(SIG_HANDSHAKE);
  1906.                                     }
  1907.  
  1908.                                     if(BoxList)
  1909.                                     {
  1910.                                         SZ_FreeBoxes(BoxList);
  1911.  
  1912.                                         BoxList = NULL;
  1913.                                     }
  1914.  
  1915.                                     SomeObject = NULL;
  1916.  
  1917.                                     Signal(ThisProcess,SIG_HANDSHAKE);
  1918.  
  1919.                                     Config -> ScreenConfig -> StatusLine = STATUSLINE_DISABLED;
  1920.  
  1921.                                     Permit();
  1922.                                 }
  1923.  
  1924.                                 if(Mask & SIG_BELL)
  1925.                                 {
  1926.                                     if(Config -> TerminalConfig -> BellMode == BELL_SYSTEM)
  1927.                                         DisplayBeep(Window -> WScreen);
  1928.                                     else
  1929.                                     {
  1930.                                         if(Screen && !Config -> ScreenConfig -> UseWorkbench && !Beeping && (Config -> TerminalConfig -> BellMode == BELL_VISIBLE || Config -> TerminalConfig -> BellMode == BELL_BOTH))
  1931.                                         {
  1932.                                             if(VisualBeep())
  1933.                                             {
  1934.                                                 Beeping = TRUE;
  1935.  
  1936.                                                 BeepCount = 1;
  1937.                                             }
  1938.                                         }
  1939.                                     }
  1940.                                 }
  1941.  
  1942.                                     /* Reset the online time counter. */
  1943.  
  1944.                                 if(Mask & SIG_RESETTIME)
  1945.                                     ResetTime = TRUE;
  1946.  
  1947.                                 if(Mask & PORTMASK(StatusTimePort))
  1948.                                 {
  1949.                                     WaitIO(StatusTimeRequest);
  1950.  
  1951.                                     break;
  1952.                                 }
  1953.                             }
  1954.  
  1955.                                 /* Reset the online time. */
  1956.  
  1957.                             if(ResetTime)
  1958.                             {
  1959.                                 StatusTimeRequest -> tr_node . io_Command = TR_GETSYSTIME;
  1960.  
  1961.                                 DoIO(StatusTimeRequest);
  1962.  
  1963.                                 OnlineTime = StatusTimeRequest -> tr_time;
  1964.                             }
  1965.  
  1966.                                 /* Count up to a minute. */
  1967.  
  1968.                             if(MinCount++ == 120)
  1969.                             {
  1970.                                 MinCount = 0;
  1971.  
  1972.                                     /* Time limit present? */
  1973.  
  1974.                                 if(LimitCount > 0)
  1975.                                     LimitCount--;
  1976.  
  1977.                                     /* Limit reached? */
  1978.  
  1979.                                 if(!LimitCount)
  1980.                                     Signal(ThisProcess,SIG_CHECK);
  1981.                             }
  1982.                         }
  1983.  
  1984.                             /* Make the colours blink. */
  1985.  
  1986.                         if(Screen && !Config -> ScreenConfig -> UseWorkbench)
  1987.                         {
  1988.                             if(Screen == IntuitionBase -> FirstScreen)
  1989.                             {
  1990.                                     /* No main screen window active? */
  1991.  
  1992.                                 if(StatusWindow)
  1993.                                 {
  1994.                                     if(!(Window -> Flags & WFLG_WINDOWACTIVE) && !(StatusWindow -> Flags & WFLG_WINDOWACTIVE))
  1995.                                         StandardColours = TRUE;
  1996.                                 }
  1997.                                 else
  1998.                                 {
  1999.                                     if(!(Window -> Flags & WFLG_WINDOWACTIVE))
  2000.                                         StandardColours = TRUE;
  2001.                                 }
  2002.  
  2003.                                     /* Menu button pressed or window disabled? */
  2004.  
  2005.                                 if(Window -> Flags & (WFLG_MENUSTATE | WFLG_INREQUEST))
  2006.                                     StandardColours = TRUE;
  2007.  
  2008.                                     /* User is currently dragging the
  2009.                                      * mouse in order to mark something
  2010.                                      * on the screen?
  2011.                                      */
  2012.  
  2013.                                 if(Marking)
  2014.                                     StandardColours = TRUE;
  2015.  
  2016.                                 Background = FALSE;
  2017.                             }
  2018.                             else
  2019.                             {
  2020.                                 if(!Background)
  2021.                                     StandardColours = TRUE;
  2022.  
  2023.                                 Background = TRUE;
  2024.                             }
  2025.  
  2026.                             if(StandardColours)
  2027.                             {
  2028.                                 if(!SetColours)
  2029.                                 {
  2030.                                     LoadRGB4(VPort,NormalColours,PaletteSize);
  2031.  
  2032.                                     SetColours = TRUE;
  2033.                                 }
  2034.  
  2035.                                 StandardColours = FlashIt = FALSE;
  2036.                             }
  2037.                             else
  2038.                             {
  2039.                                     /* Are we to flash the display? */
  2040.  
  2041.                                 if(Config -> ScreenConfig -> Blinking)
  2042.                                 {
  2043.                                     if(Screen == IntuitionBase -> FirstScreen)
  2044.                                     {
  2045.                                         if(FlashIt)
  2046.                                         {
  2047.                                             LoadRGB4(VPort,BlinkColours,PaletteSize);
  2048.  
  2049.                                             SetColours = FALSE;
  2050.                                         }
  2051.                                         else
  2052.                                         {
  2053.                                             LoadRGB4(VPort,NormalColours,PaletteSize);
  2054.  
  2055.                                             SetColours = TRUE;
  2056.                                         }
  2057.                                     }
  2058.  
  2059.                                     FlashIt ^= TRUE;
  2060.                                 }
  2061.                             }
  2062.                         }
  2063.                     }
  2064.  
  2065.                     CloseDevice(StatusTimeRequest);
  2066.                 }
  2067.  
  2068.                 DeleteIORequest(StatusTimeRequest);
  2069.             }
  2070.  
  2071.             DeleteMsgPort(StatusTimePort);
  2072.         }
  2073.  
  2074.         if(StatusDisplayTask)
  2075.         {
  2076.             Forbid();
  2077.  
  2078.             Signal(StatusDisplayTask,SIG_KILL);
  2079.  
  2080.             ClrSignal(SIG_HANDSHAKE);
  2081.  
  2082.             Wait(SIG_HANDSHAKE);
  2083.  
  2084.             Permit();
  2085.         }
  2086.  
  2087.         if(BoxList)
  2088.             SZ_FreeBoxes(BoxList);
  2089.  
  2090.         if(CheckSignal(SIG_CLOSEWINDOW))
  2091.             Signal(ThisProcess,SIG_HANDSHAKE);
  2092.     }
  2093.  
  2094.         /* Signal the father process that we're done
  2095.          * and quietly remove ourselves.
  2096.          */
  2097.  
  2098.     Forbid();
  2099.  
  2100.     Signal(ThisProcess,SIG_HANDSHAKE);
  2101.  
  2102.     StatusProcess = NULL;
  2103. }
  2104.